﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenExpressApp.Editors;
using System.Windows.Controls;
using System.Windows;
using Csla.Wpf;
using System.Windows.Data;
using OpenExpressApp.WPF.Controls;

namespace OpenExpressApp.Module.WPF.Editors
{
    /// <summary>
    /// WPF下的属性编辑器
    /// 
    /// 建立LabelControl、焦点设置ReadOnly属性
    /// </summary>
    public abstract class WPFPropertyEditor : PropertyEditor, IWPFPropertyEditor, IWPFControlGenerator
    {
        private IWPFControlGenerator _readOnlyControlGenerator;
        private IWPFControlGenerator _labelControlGenerator;

        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="propertyInfo">一个初始的编辑属性</param>
        /// <param name="view"></param>
        public WPFPropertyEditor(BusinessObjectPropertyInfo propertyInfo, IObjectView view)
            : base(view)
        {
            this._readOnlyControlGenerator = new _ReadOnlyControlGenerator(this);
            this._labelControlGenerator = new _LabelControlGenerator(this);

            //var readonlyChecker = Unity.Instance.Resolve<IReadOnlyChecker>();
            
            IList<IReadOnlyChecker> readonlyCheckerList =
                RulesRegister.Instance.ReadOnlyRegister.GetReadOnlyCheckList(this.View.EntityType);
            foreach (IReadOnlyChecker item in readonlyCheckerList)
            {
                this.RegisterChecker(item);
            }

            var visibleChecker =
                RulesRegister.Instance.VisibleCheckerRegister.GetVisibleCheckerList(this.View.EntityType);
            foreach (IVisibleChecker item in visibleChecker)
            {
                this.RegisterChecker(item);
            }

            this.PropertyInfo = propertyInfo;
        }

        public override IControlGenerator EditingControlGenerator
        {
            get
            {
                return this;
            }
        }
        public override IControlGenerator LabelControlGenerator
        {
            get
            {
                return this._labelControlGenerator;
            }
        }
        public override IControlGenerator ReadOnlyControlGenerator
        {
            get
            {
                return this._readOnlyControlGenerator;
            }
        }

        /// <summary>
        /// 子类在这个方法里面生成一个用于Edit的WPF Control
        /// </summary>
        /// <returns></returns>
        protected abstract FrameworkElement CreateEditingElement();
        /// <summary>
        /// 返回一个StackPanel，
        /// 里面是一个Label和一个PropertyStatus
        /// </summary>
        /// <returns></returns>
        protected virtual FrameworkElement CreateLabelElement()
        {
            StackPanel panel = new StackPanel() { Orientation = Orientation.Horizontal };

            //Label，
            Label l = new Label()
            {
                Content = PropertyInfo.Label,
                Target = Control
            };
            l.SetValue(WPFMeta.RequiredProperty, PropertyInfo.Required);
            panel.Children.Add(l);

            //PropertyStatus，绑定状态到对象属性
            PropertyStatus ps = new PropertyStatus()
            {
                Property = PropertyInfo.Name,
                Target = Control
            };
            Binding psbinging = new Binding();
            ps.SetBinding(PropertyStatus.SourceProperty, psbinging);
            panel.Children.Add(ps);

            return panel;
        }
        /// <summary>
        /// 生成一个只读的控件
        /// </summary>
        /// <returns></returns>
        protected virtual FrameworkElement CreateReadOnlyElement()
        {
            TextBox tb = new TextBox();

            Binding binding = new Binding(this.PropertyInfo.Name);
            binding.Mode = BindingMode.OneWay;

            this.PrepareBinding(binding);
            tb.SetBinding(TextBox.TextProperty, binding);
            tb.IsReadOnly = true;

            return tb;
        }
        /// <summary>
        /// 为ReadOnlyControl准备binding的属性。
        /// </summary>
        /// <param name="binding"></param>
        protected virtual void PrepareBinding(Binding binding) { }
        protected override object CreateEditingControlCore()
        {
            return this.CreateEditingElement();
        }

        #region IWPFPropertyEditor Members

        public new FrameworkElement Control
        {
            get
            {
                return base.Control as FrameworkElement;
            }
        }
        public new FrameworkElement LabelControl
        {
            get
            {
                return base.LabelControl as FrameworkElement;
            }
        }
        public new FrameworkElement ReadOnlyControl
        {
            get
            {
                return base.ReadOnlyControl as FrameworkElement;
            }
        }

        object IControlGenerator.CreateControl()
        {
            return this.CreateEditingElement();
        }
        FrameworkElement IWPFControlGenerator.CreateControl()
        {
            return this.CreateEditingElement();
        }
        IWPFControlGenerator IWPFPropertyEditor.EditingControlGenerator
        {
            get
            {
                return this;
            }
        }
        IWPFControlGenerator IWPFPropertyEditor.LabelControlGenerator
        {
            get
            {
                return this._labelControlGenerator;
            }
        }
        IWPFControlGenerator IWPFPropertyEditor.ReadOnlyControlGenerator
        {
            get
            {
                return this._readOnlyControlGenerator;
            }
        }

        #endregion

        #region Delegate Classes
        //内部实现：由于一个类只能对一个接口以唯一种方式实现，所以这里使用两个代理类，代理接口的实现到WPFPropertyEditor上。
        //类名使用了下划线，是避免与属性重名。

        private class _ReadOnlyControlGenerator : IWPFControlGenerator
        {
            private WPFPropertyEditor _editor;

            public _ReadOnlyControlGenerator(WPFPropertyEditor editor)
            {
                if (editor == null) throw new ArgumentNullException("editor");

                this._editor = editor;
            }

            #region IWPFControlGenerator Members

            public FrameworkElement CreateControl()
            {
                return this._editor.CreateReadOnlyElement();
            }

            #endregion

            #region IControlGenerator Members

            object IControlGenerator.CreateControl()
            {
                return this.CreateControl();
            }

            #endregion
        }
        private class _LabelControlGenerator : IWPFControlGenerator
        {
            private WPFPropertyEditor _editor;

            public _LabelControlGenerator(WPFPropertyEditor editor)
            {
                if (editor == null) throw new ArgumentNullException("editor");

                this._editor = editor;
            }

            #region IWPFControlGenerator Members

            public FrameworkElement CreateControl()
            {
                return this._editor.CreateLabelElement();
            }

            #endregion

            #region IControlGenerator Members

            object IControlGenerator.CreateControl()
            {
                return this.CreateControl();
            }

            #endregion
        }

        #endregion
    }
}